package com.jml;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;
import java.util.List;


@SpringBootApplication
public class SentinelProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SentinelProviderApplication.class, args);
        ////初始化熔断策略，代码设置熔断，不在dashboard上设置
        initRule();
        //纯代码流控设置，不用再dashboard中配置
        initFlowRule();//初始化流控规则
    }

    public static void initRule() {
        List<DegradeRule> rules = new ArrayList<>();
        // 获取定义的规则
        DegradeRule rule = slowRequestDegradeRule();
        DegradeRule rule1 = errorRatioDegradeRule();
        DegradeRule rule2 = errorCountDegradeRule();
        rules.add(rule);
        rules.add(rule1);
        rules.add(rule2);
        DegradeRuleManager.loadRules(rules);
    }
    //慢调用比例 熔断降级规则
    public static DegradeRule slowRequestDegradeRule(){
        //创建一个降级规则实例
        DegradeRule rule = new DegradeRule();
        //设置配置熔断规则的资源名称
        rule.setResource("getDepartById");
        //熔断策略：慢调用比例、异常比例、异常数
        rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        //设置阈值：RT的时间，单位毫秒。若一个请求获取到响应的时间超出该值，则会将该请求统计 为“慢调用”
        rule.setCount(200);
        //熔断恢复时间窗口，单位秒
        rule.setTimeWindow(30);
        //可触发熔断的最小请求数，默认是5个
        rule.setMinRequestAmount(5);
        // 设置发生慢调用的比例
        rule.setSlowRatioThreshold(0.5);
        return rule;
    }

    //异常比
    private static DegradeRule errorRatioDegradeRule(){
        //创建一个降级规则实例
        DegradeRule rule = new DegradeRule();
        //资源名
        rule.setResource("getDepartById");
        // 指定熔断规则为 异常比例
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
         //设置阈值：发生熔断的异常请求比例
        rule.setCount(0.5);
         rule.setTimeWindow(60);
         rule.setMinRequestAmount(5);
         return rule;
    }

    //异常数
    private static DegradeRule errorCountDegradeRule() {
        DegradeRule rule = new DegradeRule();
        rule.setResource("getDepartById");
        // 指定熔断规则为 异常数量
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        // 设置阈值：发生熔断的异常请求数量
        rule.setCount(5);
        rule.setTimeWindow(60);
        rule.setMinRequestAmount(5);
        return rule;
    }

    //限流
    public static void initFlowRule() {
        List<FlowRule> flowRules = new ArrayList<>();
        FlowRule qpsRule = qpsFlowRule();
        flowRules.add(qpsRule);
        FlowRuleManager.loadRules(flowRules);
    }

    private static FlowRule qpsFlowRule() {
        //创建流控规则对象
        FlowRule qpsRule = new FlowRule();
        //设置流控资源名称
        qpsRule.setResource("qpsFlowRule");
        //设置流控规则【QPS和线程数】
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        //设置QPS数为1
        qpsRule.setCount(1);
        //值为default，表示对请求来源不做限定
        qpsRule.setLimitApp("default");
        return qpsRule;
    }

    //线程隔离流控
    private static FlowRule threadFlowRule() {
        FlowRule qpsRule = new FlowRule();
        qpsRule.setResource("threadFlowRule");
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
        qpsRule.setCount(20);
        qpsRule.setLimitApp("default");
        return qpsRule;
    }

    // QPS 默认流控
    private static FlowRule qpsFlowRule001() {
        FlowRule qpsRule = new FlowRule();
        qpsRule.setResource("qpsFlowRule");
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        qpsRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        qpsRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        qpsRule.setCount(1); qpsRule.setLimitApp("default");
        return qpsRule;
    }

    // 关联流控模式
    private static FlowRule qpsRelateFowRule() {
        FlowRule qpsRule = new FlowRule();
        qpsRule.setResource("qpsRelateFlowRule");
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        qpsRule.setCount(1);
        qpsRule.setStrategy(RuleConstant.STRATEGY_RELATE);
        qpsRule.setRefResource("qpsFlowRule_list");
        qpsRule.setLimitApp("default");
        return qpsRule;
    }

    //链路流控模式
    private static FlowRule qpsChainFlowRule() {
        FlowRule qpsRule = new FlowRule();
        qpsRule.setResource("qpsChainFlowRule");
        qpsRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        qpsRule.setCount(1);
        qpsRule.setStrategy(RuleConstant.STRATEGY_CHAIN);
        qpsRule.setRefResource("/provider/depart/list");
        qpsRule.setLimitApp("default");
        return qpsRule;
    }
}
